package com.gitee.mrj.aiboot.core.sf.generators.type;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.gitee.mrj.aiboot.annotation.config.sf.type.AlainObject;
import com.gitee.mrj.aiboot.core.sf.generators.FormDefinitionGenerator;
import com.gitee.mrj.aiboot.core.sf.generators.UIForm;
import com.gitee.mrj.aiboot.core.sf.schema.UiFormSchemaGenerator;
import com.gitee.mrj.aiboot.core.util.ReflectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

@Component
public class AlainObjectGenerator implements FormDefinitionGenerator {
    @Override
    public void generate(UIForm root, Field field, UIForm node) {
        if (node.getLevel() > 2) {
            return;
        }
        AlainObject alainField = AnnotatedElementUtils.findMergedAnnotation(field, AlainObject.class);
        ObjectNode schema = node.getSchema();
        ObjectNode ui = node.getUi();
        node.getUi().put("widget", "object");

        schema.put("type", SFSchemaType.OBJECT.toString());
        putInt(schema, "maxProperties", alainField.maxProperties());
        putInt(schema, "minProperties", alainField.minProperties());


        UiFormSchemaGenerator.buildProperties(field.getType(), node);
        List<Field> fields = ReflectionUtils.findAllAlainFields(field.getType());
        UiFormSchemaGenerator.buildOrder(fields, ui);
        Map<Field, UIForm> nodeMap = UiFormSchemaGenerator.initFieldsFormDefinition(node, fields);
        ObjectNode properties = schema.putObject("properties");
        nodeMap.forEach((key, form) -> {
            properties.set(key.getName(), form.getSchema());
            if (form.getUi().size() > 0) {
                ui.set("$" + key.getName(), form.getUi());
            }
        });
    }


    @Override
    public void generate(UIForm root, Class clazz) {
        AlainObject alainField = AnnotatedElementUtils.findMergedAnnotation(clazz, AlainObject.class);
        ObjectNode schema = root.getSchema();
        root.getUi().put("widget", SFSchemaType.OBJECT.toString());
        schema.put("title", alainField.title());
        if (StringUtils.isNotBlank(alainField.description())) {
            schema.put("description", alainField.description());
        }
    }

    @Override
    public Class[] supports() {
        return new Class[]{AlainObject.class};
    }
}
